import * as fs from 'fs';

export interface OptimizationResult {
  success: boolean;
  message: string;
  filesModified: string[];
  optimizationsApplied: string[];
  errors?: string[];
}

/**
 * 简单但可靠的Java8优化器
 */
export class SimpleJava8Optimizer {
  
  async optimizeFile(filePath: string, features?: string[]): Promise<OptimizationResult> {
    const result: OptimizationResult = {
      success: false,
      message: '',
      filesModified: [],
      optimizationsApplied: [],
      errors: []
    };

    try {
      console.error(`[SimpleJava8Optimizer] 开始优化文件: ${filePath}`);
      
      const originalContent = fs.readFileSync(filePath, 'utf-8');
      let modifiedContent = originalContent;
      let hasChanges = false;
      
      const featuresToOptimize = features || ['lambda', 'stream', 'optional'];
      
      for (const feature of featuresToOptimize) {
        console.error(`[SimpleJava8Optimizer] 应用优化: ${feature}`);
        
        switch (feature) {
          case 'lambda':
            const lambdaResult = this.optimizeLambda(modifiedContent);
            if (lambdaResult.changed) {
              modifiedContent = lambdaResult.content;
              result.optimizationsApplied.push(...lambdaResult.changes);
              hasChanges = true;
            }
            break;
            
          case 'stream':
            const streamResult = this.optimizeStream(modifiedContent);
            if (streamResult.changed) {
              modifiedContent = streamResult.content;
              result.optimizationsApplied.push(...streamResult.changes);
              hasChanges = true;
            }
            break;
            
          case 'optional':
            const optionalResult = this.optimizeOptional(modifiedContent);
            if (optionalResult.changed) {
              modifiedContent = optionalResult.content;
              result.optimizationsApplied.push(...optionalResult.changes);
              hasChanges = true;
            }
            break;
        }
      }
      
      if (hasChanges) {
        // 添加必要的import
        modifiedContent = this.addImports(modifiedContent, result.optimizationsApplied);
        
        console.error(`[SimpleJava8Optimizer] 文件内容已修改，准备写入`);
        console.error(`[SimpleJava8Optimizer] 原始长度: ${originalContent.length}, 新长度: ${modifiedContent.length}`);
        
        // 写入文件
        fs.writeFileSync(filePath, modifiedContent, 'utf-8');
        
        // 验证文件已写入
        const verifyContent = fs.readFileSync(filePath, 'utf-8');
        if (verifyContent === modifiedContent) {
          console.error(`[SimpleJava8Optimizer] 文件成功写入并验证`);
          result.filesModified.push(filePath);
          result.success = true;
          result.message = `成功应用 ${result.optimizationsApplied.length} 个优化`;
        } else {
          console.error(`[SimpleJava8Optimizer] 文件写入验证失败`);
          result.errors?.push('文件写入后验证失败');
        }
      } else {
        result.success = true;
        result.message = '未找到可优化的代码';
        console.error(`[SimpleJava8Optimizer] 未找到可优化的代码`);
      }
      
    } catch (error) {
      result.errors?.push(`优化失败: ${error}`);
      result.message = `优化失败: ${error}`;
      console.error(`[SimpleJava8Optimizer] 错误:`, error);
    }
    
    return result;
  }
  
  private optimizeLambda(content: string): { content: string, changed: boolean, changes: string[] } {
    const changes: string[] = [];
    let newContent = content;
    let changed = false;
    
    // 1. Runnable匿名类 -> Lambda
    const runnableRegex = /new\s+Runnable\s*\(\s*\)\s*\{\s*@Override\s*public\s+void\s+run\s*\(\s*\)\s*\{([^}]*)\}\s*\}/g;
    newContent = newContent.replace(runnableRegex, (match, body) => {
      changed = true;
      changes.push('Runnable匿名类转换为Lambda');
      return `() -> {${body}}`;
    });
    
    // 2. Comparator匿名类 -> Lambda
    const comparatorRegex = /new\s+Comparator<(\w+)>\s*\(\s*\)\s*\{\s*@Override\s*public\s+int\s+compare\s*\(\s*(\w+)\s+(\w+),\s*\2\s+(\w+)\s*\)\s*\{([^}]*)\}\s*\}/g;
    newContent = newContent.replace(comparatorRegex, (match, type, paramType, param1, param2, body) => {
      changed = true;
      changes.push('Comparator匿名类转换为Lambda');
      return `(${param1}, ${param2}) -> {${body}}`;
    });
    
    // 3. Callable匿名类 -> Lambda
    const callableRegex = /new\s+Callable<(\w+)>\s*\(\s*\)\s*\{\s*@Override\s*public\s+\1\s+call\s*\(\s*\)\s*\{([^}]*)\}\s*\}/g;
    newContent = newContent.replace(callableRegex, (match, returnType, body) => {
      changed = true;
      changes.push('Callable匿名类转换为Lambda');
      return `() -> {${body}}`;
    });
    
    // 4. Predicate匿名类 -> Lambda
    const predicateRegex = /new\s+Predicate<(\w+)>\s*\(\s*\)\s*\{\s*@Override\s*public\s+boolean\s+test\s*\(\s*\1\s+(\w+)\s*\)\s*\{([^}]*)\}\s*\}/g;
    newContent = newContent.replace(predicateRegex, (match, type, param, body) => {
      changed = true;
      changes.push('Predicate匿名类转换为Lambda');
      return `${param} -> {${body}}`;
    });
    
    // 5. Function匿名类 -> Lambda
    const functionRegex = /new\s+Function<(\w+),\s*(\w+)>\s*\(\s*\)\s*\{\s*@Override\s*public\s+\2\s+apply\s*\(\s*\1\s+(\w+)\s*\)\s*\{([^}]*)\}\s*\}/g;
    newContent = newContent.replace(functionRegex, (match, inputType, outputType, param, body) => {
      changed = true;
      changes.push('Function匿名类转换为Lambda');
      return `${param} -> {${body}}`;
    });
    
    // 6. 简单的Lambda表达式优化 - 单语句Lambda去掉大括号
    const simpleLambdaRegex = /(\w+)\s*->\s*\{\s*return\s+([^;]+);\s*\}/g;
    newContent = newContent.replace(simpleLambdaRegex, (match, param, expression) => {
      changed = true;
      changes.push('简化Lambda表达式（去掉大括号和return）');
      return `${param} -> ${expression}`;
    });
    
    // 7. 方法引用优化 - Lambda调用对象方法转为方法引用
    const methodRefRegex = /(\w+)\s*->\s*\1\.(\w+)\(\s*\)/g;
    newContent = newContent.replace(methodRefRegex, (match, param, method) => {
      changed = true;
      changes.push(`Lambda转换为方法引用: ${method}`);
      return `${param.charAt(0).toUpperCase() + param.slice(1)}::${method}`;
    });
    
    console.error(`[optimizeLambda] 找到 ${changes.length} 个Lambda优化`);
    
    return { content: newContent, changed, changes };
  }
  
  private optimizeStream(content: string): { content: string, changed: boolean, changes: string[] } {
    const changes: string[] = [];
    let newContent = content;
    let changed = false;
    
    // 1. 简单的for循环转Stream（只处理最简单的情况）
    // for (Type item : collection) { list.add(item); }
    const simpleForEachRegex = /for\s*\(\s*(\w+)\s+(\w+)\s*:\s*(\w+)\s*\)\s*\{\s*(\w+)\.add\s*\(\s*\2\s*\)\s*;\s*\}/g;
    
    newContent = newContent.replace(simpleForEachRegex, (match, type, item, collection, targetList) => {
      changed = true;
      changes.push(`for-each循环转换为addAll: ${collection}`);
      return `${targetList}.addAll(${collection});`;
    });
    
    // 2. 带过滤的for循环
    // for (Type item : collection) { if (condition) { list.add(item); } }
    const filterForEachRegex = /for\s*\(\s*(\w+)\s+(\w+)\s*:\s*(\w+)\s*\)\s*\{\s*if\s*\(([^)]+)\)\s*\{\s*(\w+)\.add\s*\(\s*\2\s*\)\s*;\s*\}\s*\}/g;
    
    newContent = newContent.replace(filterForEachRegex, (match, type, item, collection, condition, targetList) => {
      changed = true;
      changes.push(`带过滤的for循环转换为Stream: ${collection}`);
      // 替换条件中的item引用
      const streamCondition = condition.replace(new RegExp(`\\b${item}\\b`, 'g'), item);
      return `${targetList}.addAll(${collection}.stream().filter(${item} -> ${streamCondition}).collect(Collectors.toList()));`;
    });
    
    // 3. 带转换的for循环
    // for (Type item : collection) { resultList.add(item.method()); }
    const mapForEachRegex = /for\s*\(\s*(\w+)\s+(\w+)\s*:\s*(\w+)\s*\)\s*\{\s*(\w+)\.add\s*\(\s*\2\.(\w+)\(\s*\)\s*\)\s*;\s*\}/g;
    
    newContent = newContent.replace(mapForEachRegex, (match, type, item, collection, targetList, method) => {
      changed = true;
      changes.push(`带转换的for循环转换为Stream.map: ${collection}`);
      return `${targetList}.addAll(${collection}.stream().map(${type}::${method}).collect(Collectors.toList()));`;
    });
    
    // 4. 简单的forEach调用
    // collection.forEach(item -> { System.out.println(item); });
    const forEachWithLambdaRegex = /(\w+)\.forEach\s*\(\s*(\w+)\s*->\s*\{\s*System\.out\.println\s*\(\s*\2\s*\)\s*;\s*\}\s*\)/g;
    
    newContent = newContent.replace(forEachWithLambdaRegex, (match, collection, item) => {
      changed = true;
      changes.push(`forEach Lambda转换为方法引用: ${collection}`);
      return `${collection}.forEach(System.out::println)`;
    });
    
    // 5. 简化forEach Lambda（没有大括号）
    // collection.forEach(item -> System.out.println(item))
    const simpleForEachLambdaRegex = /(\w+)\.forEach\s*\(\s*(\w+)\s*->\s*System\.out\.println\s*\(\s*\2\s*\)\s*\)/g;
    
    newContent = newContent.replace(simpleForEachLambdaRegex, (match, collection, item) => {
      changed = true;
      changes.push(`forEach Lambda转换为方法引用: ${collection}`);
      return `${collection}.forEach(System.out::println)`;
    });
    
    // 6. 计数优化 - for循环计数转为Stream count
    // int count = 0; for (Type item : collection) { if (condition) count++; }
    const countForLoopRegex = /int\s+count\s*=\s*0\s*;\s*for\s*\(\s*(\w+)\s+(\w+)\s*:\s*(\w+)\s*\)\s*\{\s*if\s*\(([^)]+)\)\s*count\+\+\s*;\s*\}/g;
    
    newContent = newContent.replace(countForLoopRegex, (match, type, item, collection, condition) => {
      changed = true;
      changes.push(`计数for循环转换为Stream.count: ${collection}`);
      const streamCondition = condition.replace(new RegExp(`\\b${item}\\b`, 'g'), item);
      return `long count = ${collection}.stream().filter(${item} -> ${streamCondition}).count();`;
    });
    
    console.error(`[optimizeStream] 找到 ${changes.length} 个Stream优化`);
    
    return { content: newContent, changed, changes };
  }
  
  private optimizeOptional(content: string): { content: string, changed: boolean, changes: string[] } {
    const changes: string[] = [];
    let newContent = content;
    let changed = false;
    
    // 1. 简单的三元运算符null检查转Optional
    // return obj != null ? obj : defaultValue;
    const ternaryNullCheckRegex = /return\s+(\w+)\s*!=\s*null\s*\?\s*\1\s*:\s*([^;]+)\s*;/g;
    
    newContent = newContent.replace(ternaryNullCheckRegex, (match, varName, defaultValue) => {
      changed = true;
      changes.push(`三元运算符null检查转换为Optional: ${varName}`);
      return `return Optional.ofNullable(${varName}).orElse(${defaultValue});`;
    });
    
    // 2. if-else return模式
    // if (obj != null) { return obj; } else { return defaultValue; }
    const ifElseReturnRegex = /if\s*\(\s*(\w+)\s*!=\s*null\s*\)\s*\{\s*return\s+\1\s*;\s*\}\s*else\s*\{\s*return\s+([^;]+)\s*;\s*\}/g;
    
    newContent = newContent.replace(ifElseReturnRegex, (match, varName, defaultValue) => {
      changed = true;
      changes.push(`if-else return转换为Optional: ${varName}`);
      return `return Optional.ofNullable(${varName}).orElse(${defaultValue});`;
    });
    
    // 3. 简单的null检查后方法调用
    // if (obj != null) { obj.method(); }
    const simpleNullCheckRegex = /if\s*\(\s*(\w+)\s*!=\s*null\s*\)\s*\{\s*\1\.(\w+)\(\s*\)\s*;\s*\}/g;
    
    newContent = newContent.replace(simpleNullCheckRegex, (match, varName, method) => {
      changed = true;
      changes.push(`null检查转换为Optional.ifPresent: ${varName}.${method}`);
      return `Optional.ofNullable(${varName}).ifPresent(${varName}::${method});`;
    });
    
    // 4. 赋值时的null检查
    // String result = str != null ? str : "default";
    const assignmentTernaryRegex = /(\w+)\s+(\w+)\s*=\s*(\w+)\s*!=\s*null\s*\?\s*\3\s*:\s*([^;]+)\s*;/g;
    
    newContent = newContent.replace(assignmentTernaryRegex, (match, type, varName, checkVar, defaultValue) => {
      changed = true;
      changes.push(`赋值时null检查转换为Optional: ${checkVar}`);
      return `${type} ${varName} = Optional.ofNullable(${checkVar}).orElse(${defaultValue});`;
    });
    
    // 5. Map的get操作优化（防止NullPointerException）
    // if (map.get(key) != null) { ... }
    const mapGetNullCheckRegex = /if\s*\(\s*(\w+)\.get\s*\(([^)]+)\)\s*!=\s*null\s*\)\s*\{\s*([^}]+)\s*\}/g;
    
    newContent = newContent.replace(mapGetNullCheckRegex, (match, mapName, key, body) => {
      changed = true;
      changes.push(`Map.get null检查转换为Optional: ${mapName}`);
      return `Optional.ofNullable(${mapName}.get(${key})).ifPresent(value -> { ${body} });`;
    });
    
    console.error(`[optimizeOptional] 找到 ${changes.length} 个Optional优化`);
    
    return { content: newContent, changed, changes };
  }
  
  private addImports(content: string, optimizations: string[]): string {
    const requiredImports = new Set<string>();
    
    // 根据优化确定需要的import
    for (const opt of optimizations) {
      if (opt.includes('Optional')) {
        requiredImports.add('import java.util.Optional;');
      }
      if (opt.includes('Stream') || opt.includes('Collectors')) {
        requiredImports.add('import java.util.stream.Collectors;');
        requiredImports.add('import java.util.stream.Stream;');
      }
      if (opt.includes('Predicate')) {
        requiredImports.add('import java.util.function.Predicate;');
      }
      if (opt.includes('Function')) {
        requiredImports.add('import java.util.function.Function;');
      }
      if (opt.includes('Callable')) {
        requiredImports.add('import java.util.concurrent.Callable;');
      }
    }
    
    // 检查内容中是否使用了这些类，如果是则添加相应的import
    if (content.includes('Collectors.')) {
      requiredImports.add('import java.util.stream.Collectors;');
    }
    if (content.includes('Optional.')) {
      requiredImports.add('import java.util.Optional;');
    }
    
    // 检查现有的import
    const existingImports = new Set<string>();
    const importRegex = /import\s+[^;]+;/g;
    let match;
    while ((match = importRegex.exec(content)) !== null) {
      existingImports.add(match[0]);
    }
    
    // 添加缺失的import
    const newImports = Array.from(requiredImports).filter(imp => !existingImports.has(imp));
    
    if (newImports.length > 0) {
      // 在package声明后添加
      const packageMatch = content.match(/package\s+[^;]+;/);
      if (packageMatch) {
        const packageEnd = packageMatch.index! + packageMatch[0].length;
        content = content.slice(0, packageEnd) + '\n\n' + newImports.join('\n') + content.slice(packageEnd);
      } else {
        // 在文件开头添加
        content = newImports.join('\n') + '\n\n' + content;
      }
    }
    
    return content;
  }
}